package ar.uba.fi.cimII7566.cuat201102.automatizacionNegroHumo.negocio;

import java.util.ArrayList;
import java.util.List;
import java.util.Observable;
import java.util.Observer;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ar.uba.fi.cimII7566.cuat201102.automatizacionNegroHumo.modelo.Camino;
import ar.uba.fi.cimII7566.cuat201102.automatizacionNegroHumo.modelo.Carro;
import ar.uba.fi.cimII7566.cuat201102.automatizacionNegroHumo.modelo.Compuerta;
import ar.uba.fi.cimII7566.cuat201102.automatizacionNegroHumo.modelo.Configuracion;
import ar.uba.fi.cimII7566.cuat201102.automatizacionNegroHumo.modelo.Deposito;
import ar.uba.fi.cimII7566.cuat201102.automatizacionNegroHumo.modelo.Descanso;
import ar.uba.fi.cimII7566.cuat201102.automatizacionNegroHumo.modelo.Entidad;
import ar.uba.fi.cimII7566.cuat201102.automatizacionNegroHumo.modelo.EnumOrden;
import ar.uba.fi.cimII7566.cuat201102.automatizacionNegroHumo.modelo.EnumSentido;
import ar.uba.fi.cimII7566.cuat201102.automatizacionNegroHumo.modelo.Esclusa;
import ar.uba.fi.cimII7566.cuat201102.automatizacionNegroHumo.modelo.Posicion;
import ar.uba.fi.cimII7566.cuat201102.automatizacionNegroHumo.modelo.Punto;
import ar.uba.fi.cimII7566.cuat201102.automatizacionNegroHumo.modelo.Recipiente;
import ar.uba.fi.cimII7566.cuat201102.automatizacionNegroHumo.modelo.Sensor;
import ar.uba.fi.cimII7566.cuat201102.automatizacionNegroHumo.negocio.comunicacion.ServicioDepositoAlmacenamiento;
import ar.uba.fi.cimII7566.cuat201102.automatizacionNegroHumo.negocio.comunicacion.ServicioSistemaGrua;

public class Simulador extends Observable {
	private List<Camino> listCaminos = new ArrayList<Camino>();
	private List<Carro> listCarro = null;
	private List<Compuerta> listCompuerta = null;
	private List<Esclusa> listEsclusa = null;
	private List<Sensor> listSensor = null;
	private Deposito deposito = null;
	private ServicioDepositoAlmacenamiento servicioDepositoAlmacenamiento = null;
	private ServicioSistemaGrua servicioSistemaGrua = null;
	private Ciclador ciclador = null;
	private Observer observer = null;
	public static long CICLOS = 0;
	boolean continuar = false;
	private int escenario = Configuracion.ESCENARIO_UNO_NORMAL;
	private int ciclosDesdePulsarBoton1 = 0;
	private int ciclosDesdePulsarBoton2 = 0;
	private int ciclosDesdePulsarBoton3 = 0;
	private int ciclosBarcoDescargado = 0;

	/**
	 * @return the ciclosDesdePulsarBoton1
	 */
	public int getCiclosDesdePulsarBoton1() {
		return ciclosDesdePulsarBoton1;
	}

	/**
	 * @param ciclosDesdePulsarBoton1 the ciclosDesdePulsarBoton1 to set
	 */
	public void setCiclosDesdePulsarBoton1(int ciclosDesdePulsarBoton1) {
		this.ciclosDesdePulsarBoton1 = ciclosDesdePulsarBoton1;
	}

	/**
	 * @return the ciclosDesdePulsarBoton2
	 */
	public int getCiclosDesdePulsarBoton2() {
		return ciclosDesdePulsarBoton2;
	}

	/**
	 * @param ciclosDesdePulsarBoton2 the ciclosDesdePulsarBoton2 to set
	 */
	public void setCiclosDesdePulsarBoton2(int ciclosDesdePulsarBoton2) {
		this.ciclosDesdePulsarBoton2 = ciclosDesdePulsarBoton2;
	}

	/**
	 * @return the ciclosDesdePulsarBoton3
	 */
	public int getCiclosDesdePulsarBoton3() {
		return ciclosDesdePulsarBoton3;
	}

	/**
	 * @param ciclosDesdePulsarBoton3 the ciclosDesdePulsarBoton3 to set
	 */
	public void setCiclosDesdePulsarBoton3(int ciclosDesdePulsarBoton3) {
		this.ciclosDesdePulsarBoton3 = ciclosDesdePulsarBoton3;
	}

	public static int CICLO = Configuracion.CICLO;

	private final Logger logger = LoggerFactory.getLogger(Simulador.class);

	public class Ciclador extends Thread {

		private boolean continuar = true;

		private Simulador simulador = null;

		public Ciclador(Simulador simulador) {
			this.simulador = simulador;
		}

		public void parar() {
			continuar = false;
		}

		public void run() {
			try {
				while (continuar) {
					if (continuar) {
						sleep(CICLO);
					}
					if (continuar) {
						simulador.ciclarInterno();
					}
				}
			} catch (Exception e) {
				continuar = false;
				logger.error(e.getMessage());
			}
		}

		/**
		 * @return the continuar
		 */
		public boolean isContinuar() {
			return continuar;
		}

		/**
		 * @param continuar
		 *            the continuar to set
		 */
		public void setContinuar(boolean continuar) {
			this.continuar = continuar;
		}
	}

	public void notifyObservers() {
		try {
			setChanged();
			super.notifyObservers();
		} catch (Exception e) {
			logger.error(e.getMessage());
		}
	}

	public void notifyObservers(Object b) {
		try {
			setChanged();
			super.notifyObservers(b);
		} catch (Exception e) {
			logger.error(e.getMessage());
		}
	}

	public void evento(Observer observer) {
		try {
			notifyObservers(observer);
		} catch (Exception e) {
			logger.error(e.getMessage());
		}
	}

	public void inicializar() throws Exception {
		try {
			setListCarro(new ArrayList<Carro>());
			listCompuerta = new ArrayList<Compuerta>();
			setListEsclusa(new ArrayList<Esclusa>());
			List<Esclusa> esclusasInicialesDeDeposito = new ArrayList<Esclusa>();
			setListSensor(new ArrayList<Sensor>());
			setServicioDepositoAlmacenamiento(new ServicioDepositoAlmacenamiento());
			setServicioSistemaGrua(new ServicioSistemaGrua());
			getServicioSistemaGrua().setCantidadRecipientes(10);
			CICLOS = 0;
			// ---------------------------------------------------------------------
			deposito = Deposito.factory();
			getListSensor().add(deposito.getSensor());
			// ---------------------------------------------------------------------
			Carro carro = Carro.factory(deposito);
			getListSensor().add(carro.getSensor());
			getListCarro().add(carro);
			carro = Carro.factory(deposito);
			getListSensor().add(carro.getSensor());
			getListCarro().add(carro);
			carro = Carro.factory(deposito);
			getListSensor().add(carro.getSensor());
			getListCarro().add(carro);
			deposito.setListCarro(getListCarro());
			// ---------------------------------------------------------------------
			Compuerta compuerta = Compuerta.factory(deposito);
			getListSensor().add(compuerta.getSensor());
			getListSensor().add(compuerta.getAnterior().getSensor());
			getListSensor().add(compuerta.getPosterior().getSensor());
			esclusasInicialesDeDeposito.add(compuerta.getAnterior());
			getListEsclusa().add((Esclusa) compuerta.getAnterior());
			getListEsclusa().add((Esclusa) compuerta.getPosterior());
			listCompuerta.add(compuerta);
			compuerta = Compuerta.factory(deposito);
			getListSensor().add(compuerta.getSensor());
			getListSensor().add(compuerta.getAnterior().getSensor());
			getListSensor().add(compuerta.getPosterior().getSensor());
			esclusasInicialesDeDeposito.add(compuerta.getAnterior());
			getListEsclusa().add((Esclusa) compuerta.getAnterior());
			getListEsclusa().add((Esclusa) compuerta.getPosterior());
			listCompuerta.add(compuerta);
			compuerta = Compuerta.factory(deposito);
			getListSensor().add(compuerta.getSensor());
			getListSensor().add(compuerta.getAnterior().getSensor());
			getListSensor().add(compuerta.getPosterior().getSensor());
			esclusasInicialesDeDeposito.add(compuerta.getAnterior());
			getListEsclusa().add((Esclusa) compuerta.getAnterior());
			getListEsclusa().add((Esclusa) compuerta.getPosterior());
			listCompuerta.add(compuerta);
			deposito.setListPosterior(esclusasInicialesDeDeposito);
			// ---------------------------------------------------------------------
			Punto punto1 = Punto.factory();
			getListSensor().add(punto1.getSensor());
			Camino camino1 = Camino.factory();
			listCaminos.add(camino1);
			getListSensor().add(camino1.getSensor());
			Punto punto2 = Punto.factory();
			getListSensor().add(punto2.getSensor());
			Camino camino2 = Camino.factory();
			listCaminos.add(camino2);
			getListSensor().add(camino2.getSensor());
			Punto punto3 = Punto.factory();
			getListSensor().add(punto3.getSensor());
			Camino camino3 = Camino.factory();
			listCaminos.add(camino3);
			getListSensor().add(camino3.getSensor());
			Punto punto4 = Punto.factory();
			getListSensor().add(punto4.getSensor());
			// ---------------------------------------------------------------------
			((Camino) listCompuerta.get(0).getPosterior().getPosterior())
					.setPosterior(punto1);
			punto1.setAnterior((Camino) listCompuerta.get(0).getPosterior()
					.getPosterior());
			listCaminos.add((Camino) listCompuerta.get(0).getPosterior()
					.getPosterior());
			getListSensor().add(
					listCompuerta.get(0).getPosterior().getPosterior()
							.getSensor());
			// ---------------------------------------------------------------------
			camino1.setAnterior(punto1);
			punto1.setPosterior(camino1);
			// ---------------------------------------------------------------------
			List<Camino> listCaminoAnterior = new ArrayList<Camino>();
			camino1.setPosterior(punto2);
			listCaminoAnterior.add(camino1);
			// ---------------------------------------------------------------------
			((Camino) listCompuerta.get(1).getPosterior().getPosterior())
					.setPosterior(punto2);
			listCaminoAnterior.add((Camino) listCompuerta.get(1).getPosterior()
					.getPosterior());
			listCaminos.add((Camino) listCompuerta.get(1).getPosterior()
					.getPosterior());
			getListSensor().add(
					listCompuerta.get(1).getPosterior().getPosterior()
							.getSensor());
			// ---------------------------------------------------------------------
			camino2.setPosterior(punto2);
			listCaminoAnterior.add(camino2);
			punto2.setListCaminoAnterior(listCaminoAnterior);
			// ---------------------------------------------------------------------
			camino3.setAnterior(punto2);
			punto2.setPosterior(camino3);
			// ---------------------------------------------------------------------
			((Camino) listCompuerta.get(2).getPosterior().getPosterior())
					.setPosterior(punto3);
			punto3.setAnterior((Camino) listCompuerta.get(2).getPosterior()
					.getPosterior());
			listCaminos.add((Camino) listCompuerta.get(2).getPosterior()
					.getPosterior());
			getListSensor().add(
					listCompuerta.get(2).getPosterior().getPosterior()
							.getSensor());
			camino2.setAnterior(punto3);
			punto3.setPosterior(camino2);
			camino3.setPosterior(punto4);
			punto4.setAnterior(camino3);
			// ---------------------------------------------------------------------
			Punto puntoDescanso1 = Punto.factory();
			getListSensor().add(puntoDescanso1.getSensor());
			Descanso descanso1 = Descanso.factory();
			getListSensor().add(descanso1.getSensor());
			Punto puntoDescanso2 = Punto.factory();
			puntoDescanso2.setSensor(null);
			Descanso descanso2 = Descanso.factory();
			getListSensor().add(descanso2.getSensor());
			Punto puntoDescanso3 = Punto.factory();
			getListSensor().add(puntoDescanso3.getSensor());
			Descanso descanso3 = Descanso.factory();
			getListSensor().add(descanso3.getSensor());
			Punto puntoDescanso4 = Punto.factory();
			puntoDescanso4.setSensor(null);
			Descanso descanso4 = Descanso.factory();
			getListSensor().add(descanso4.getSensor());
			Punto puntoDescanso5 = Punto.factory();
			getListSensor().add(puntoDescanso5.getSensor());
			Descanso descanso5 = Descanso.factory();
			getListSensor().add(descanso5.getSensor());
			Punto puntoDescanso6 = Punto.factory();
			puntoDescanso6.setSensor(null);
			Descanso descanso6 = Descanso.factory();
			getListSensor().add(descanso6.getSensor());
			Punto puntoDescanso7 = Punto.factory();
			getListSensor().add(puntoDescanso7.getSensor());
			Descanso descanso7 = Descanso.factory();
			getListSensor().add(descanso7.getSensor());
			Punto puntoDescanso8 = Punto.factory();
			puntoDescanso8.setSensor(null);
			Descanso descanso8 = Descanso.factory();
			getListSensor().add(descanso8.getSensor());
			// ---------------------------------------------------------------------
			camino1.setPuntoDescanso(puntoDescanso1);
			puntoDescanso1.setPropietario(camino1);
			((Camino) listCompuerta.get(1).getPosterior().getPosterior())
					.setPuntoDescanso(puntoDescanso3);
			puntoDescanso3.setPropietario(((Camino) listCompuerta.get(1)
					.getPosterior().getPosterior()));
			camino2.setPuntoDescanso(puntoDescanso5);
			puntoDescanso5.setPropietario(camino2);
			camino3.setPuntoDescanso(puntoDescanso7);
			puntoDescanso7.setPropietario(camino3);
			// ---------------------------------------------------------------------
			puntoDescanso1.setPosterior(descanso1);
			descanso1.setAnterior(puntoDescanso1);
			descanso1.setPosterior(puntoDescanso2);
			puntoDescanso2.setAnterior(descanso1);
			puntoDescanso2.setPosterior(descanso2);
			descanso2.setAnterior(puntoDescanso2);
			descanso2.setPosterior(puntoDescanso3);
			puntoDescanso3.setAnterior(descanso2);
			puntoDescanso3.setPosterior(descanso3);
			descanso3.setAnterior(puntoDescanso3);
			descanso3.setPosterior(puntoDescanso4);
			puntoDescanso4.setAnterior(descanso3);
			puntoDescanso4.setPosterior(descanso4);
			descanso4.setAnterior(puntoDescanso4);
			descanso4.setPosterior(puntoDescanso5);
			puntoDescanso5.setAnterior(descanso4);
			puntoDescanso5.setPosterior(descanso5);
			descanso5.setAnterior(puntoDescanso5);
			descanso5.setPosterior(puntoDescanso6);
			puntoDescanso6.setAnterior(descanso5);
			puntoDescanso6.setPosterior(descanso6);
			descanso6.setAnterior(puntoDescanso6);
			descanso6.setPosterior(puntoDescanso7);
			puntoDescanso7.setAnterior(descanso6);
			puntoDescanso7.setPosterior(descanso7);
			descanso7.setAnterior(puntoDescanso7);
			descanso7.setPosterior(puntoDescanso8);
			puntoDescanso8.setAnterior(descanso7);
			puntoDescanso8.setPosterior(descanso8);
			descanso8.setAnterior(puntoDescanso8);
			descanso8.setPosterior(puntoDescanso1);
			puntoDescanso1.setAnterior(descanso8);
			// ---------------------------------------------------------------------
		} catch (Exception e) {
			logger.error(e.getMessage());
			throw e;
		}
	}

	private void activarSensoresProximidad(Entidad entidad1, Entidad entidad2)
			throws Exception {
		try {
			logger.debug("Seteo eventos proximidad");
			entidad1.recibirEventoProximidad(entidad2);
			entidad2.recibirEventoProximidad(entidad1);
		} catch (Exception e) {
			logger.error(e.getMessage());
			throw e;
		}
	}

	private boolean seguir() throws Exception {
		try {
			return (continuar && ciclador.isContinuar());
		} catch (Exception e) {
			logger.error(e.getMessage());
			throw e;
		}
	}

	private void procesoNormal(Carro carro) throws Exception {
		try {
			if (carro.getOrden().equals(EnumOrden.IR_BUSCAR_RECIPIENTE)) {
				if (carro.getSentido().equals(EnumSentido.HACIA_RECIPIENTE)) {
					buscarRecipiente(carro);
				} else if (carro.getSentido()
						.equals(EnumSentido.HACIA_DEPOSITO)) {
					buscarDeposito(carro);
				}
			} else if (carro.getOrden().equals(EnumOrden.IR_DEPOSITO)) {
				buscarDeposito(carro);
			} else if (carro.getOrden().equals(EnumOrden.IR_DESCANSO)) {
				irADescanso(carro);
			} else if (carro.getOrden().equals(EnumOrden.PARAR)) {
				// HECHO !
			}
		} catch (Exception e) {
			logger.error(e.getMessage());
			throw e;
		}
	}

	private int cantidadCarrosYendoADescanso() throws Exception {
		try {
			int retorno = 0;
			for (Carro carro : listCarro) {
				if (carro.getOrden().equals(EnumOrden.IR_DESCANSO)) {
					retorno++;
				}
			}
			return retorno;
		} catch (Exception e) {
			logger.error(e.getMessage());
			throw e;
		}
	}

	public synchronized void ciclarInterno() {
		try {
			Recipiente.idFactory = 0;
			Carro carro = null;
			continuar = true;
			Carro carroMasProximoACaminoUnificado = null;
			boolean proseguir = true;
			for (int i = 0; ((i < getListCarro().size()) && (ciclador
					.isContinuar())); i++) {
				if (!servicioSistemaGrua.hayRecipientesPorEntregar()) {
					if (ciclosBarcoDescargado == 0) {
						ciclosBarcoDescargado = (int) CICLOS;
					}
					if ((CICLOS - ciclosBarcoDescargado) >= 100) {
						servicioSistemaGrua.setCantidadRecipientes(10);
						ciclosBarcoDescargado = 0;
					}
				}
				switch (getEscenario()) {
				case (Configuracion.ESCENARIO_DOS_OBSTACULO):
					Camino camino1 = (Camino) listCompuerta.get(0)
							.getPosterior().getPosterior();
					Camino camino3 = (Camino) listCompuerta.get(2)
							.getPosterior().getPosterior();
					Camino camino6 = (Camino) listCompuerta.get(1)
							.getPosterior().getPosterior().getPosterior()
							.getPosterior();
					if (((CICLOS - ciclosDesdePulsarBoton2) >= 000) && ((CICLOS - ciclosDesdePulsarBoton2) <= 100)) {
						camino1.recibirEventoObstaculo(null);
					}
					if (((CICLOS - ciclosDesdePulsarBoton2) >= 100) && ((CICLOS - ciclosDesdePulsarBoton2) <= 200)) {
						camino1.eliminarEventoObstaculo();
						camino3.recibirEventoObstaculo(null);
					}
					if (((CICLOS - ciclosDesdePulsarBoton2) >= 200) && ((CICLOS - ciclosDesdePulsarBoton2) <= 300)) {
						camino3.eliminarEventoObstaculo();
						camino6.recibirEventoObstaculo(null);
					}
					if ((CICLOS - ciclosDesdePulsarBoton2) >= 300) {
						camino6.eliminarEventoObstaculo();
					}
					break;
				case (Configuracion.ESCENARIO_TRES_VIENTO):
					if (((CICLOS - ciclosDesdePulsarBoton3) >= 000) && ((CICLOS - ciclosDesdePulsarBoton3) <= 100)) {
						if ((!listCarro.get(0).getInfraestructura().getTipo()
								.equals("Esclusa"))
								&& (!listCarro.get(0).getInfraestructura()
										.getTipo().equals("Compuerta"))
								&& (!listCarro.get(0).getInfraestructura()
										.getTipo().equals("Deposito"))) {
							listCarro.get(0).recibirEventoViento(null, "10kmh");
						} else {
							listCarro.get(0).eliminarEventoViento();
						}
					}
					if (((CICLOS - ciclosDesdePulsarBoton3) >= 100) && ((CICLOS - ciclosDesdePulsarBoton3) <= 200)) {
						listCarro.get(0).eliminarEventoViento();
						if ((!listCarro.get(1).getInfraestructura().getTipo()
								.equals("Esclusa"))
								&& (!listCarro.get(1).getInfraestructura()
										.getTipo().equals("Compuerta"))
								&& (!listCarro.get(1).getInfraestructura()
										.getTipo().equals("Deposito"))) {
							listCarro.get(1).recibirEventoViento(null, "10kmh");
						} else {
							listCarro.get(1).eliminarEventoViento();
						}
					}
					if (((CICLOS - ciclosDesdePulsarBoton3) >= 200) && ((CICLOS - ciclosDesdePulsarBoton3) <= 300)) {
						listCarro.get(1).eliminarEventoViento();
						if ((!listCarro.get(2).getInfraestructura().getTipo()
								.equals("Esclusa"))
								&& (!listCarro.get(2).getInfraestructura()
										.getTipo().equals("Compuerta"))
								&& (!listCarro.get(2).getInfraestructura()
										.getTipo().equals("Deposito"))) {
							listCarro.get(2).recibirEventoViento(null, "10kmh");
						} else {
							listCarro.get(2).eliminarEventoViento();
						}
					}
					if ((CICLOS - ciclosDesdePulsarBoton3) >= 300) {
						listCarro.get(2).eliminarEventoViento();
					}
					break;
				case (Configuracion.ESCENARIO_UNO_NORMAL):
					//
					break;
				}
				carro = getListCarro().get(i);
				logger.debug("---------------------------------------------------");
				logger.debug(carro.toString());
				logger.debug("Ciclos: " + CICLOS);
				logger.debug("Velocidad carro 1: "
						+ listCarro.get(0).getVelocidad());
				logger.debug("Velocidad carro 2: "
						+ listCarro.get(1).getVelocidad());
				logger.debug("Velocidad carro 3: "
						+ listCarro.get(2).getVelocidad());
				logger.debug("Cantidad de recipientes: "
						+ getServicioSistemaGrua().getCantidadRecipientes());
				continuar = true;
				proseguir = true;
				if (carro.getInfraestructura().getTipo().equals("Camino")
						&& carro.getSentido().equals(
								EnumSentido.HACIA_RECIPIENTE)) {
					carroMasProximoACaminoUnificado = getCarroPrimeroEnUnificado();
					if (carroMasProximoACaminoUnificado.getId().intValue() != carro
							.getId().intValue()) {
						Object[] resultado = getTiempoHastaUnificado(carroMasProximoACaminoUnificado);
						int tiempoCarroProximo = (Integer) resultado[0];
						resultado = getTiempoHastaUnificado(carro);
						int tiempoCarro = (Integer) resultado[0];
						if (tiempoCarroProximo == tiempoCarro) {
							if (carro.getId().intValue() < carroMasProximoACaminoUnificado
									.getId().intValue()) {
								carro.setOrden(EnumOrden.IR_BUSCAR_RECIPIENTE);
								carroMasProximoACaminoUnificado
										.setOrden(EnumOrden.IR_DESCANSO);
								proseguir = false;
							}
						}
						if (proseguir) {
							if (cantidadCarrosYendoADescanso() >= 2) {
								proseguir = false;
							}
						}
						if (proseguir) {
							if (carroMasProximoACaminoUnificado.getSentido()
									.equals(EnumSentido.HACIA_RECIPIENTE)) {
								carro.setOrden(EnumOrden.IR_DESCANSO);
							} else {
								if (carroMasProximoACaminoUnificado
										.getInfraestructura().getTipo()
										.equals("Camino")) {
									if (carroMasProximoACaminoUnificado
											.getInfraestructura().getId()
											.intValue() == 6) {
										if (carroMasProximoACaminoUnificado
												.getPosicion().getY() >= Configuracion.LARGO_CAMINO_DESCANSO) {
											carro.setOrden(EnumOrden.IR_DESCANSO);
										}
									}
								} else if (carroMasProximoACaminoUnificado
										.getInfraestructura().getTipo()
										.equals("Descanso")) {
									carro.setOrden(EnumOrden.IR_DESCANSO);
								}
							}
						} else {
							procesoNormal(carro);
						}
					}
				}
				if (seguir()) {
					procesoNormal(carro);
				}
				if (ciclador.isContinuar()) {
					notifyObservers(this.observer);
					CICLOS++;
				} else {
					i = 4;
				}
			}
		} catch (Exception e) {
			logger.error(e.getMessage());
		}
	}

	private boolean sePuedeSalirDelDescanso(Carro car) throws Exception {
		try {
			boolean uno = false;
			Carro carro = listCarro.get(0);
			if (carro.getSentido().equals(EnumSentido.HACIA_DEPOSITO)) {
				if (carro.getInfraestructura().getTipo().equals("Camino")) {
					if (carro.getInfraestructura().getId().intValue() == 6) {
						if (carro.getPosicion().getY() <= Configuracion.LARGO_CAMINO_DESCANSO) {
							uno = true;
						}
					} else {
						uno = true;
					}
				}
			} else {
				if (carro.getInfraestructura().getTipo().equals("Camino")) {
					if (carro.getInfraestructura().getId().intValue() != 6) {
						uno = true;
					}
				}
			}
			if (!uno && carro.getInfraestructura().getTipo().equals("Descanso")) {
				uno = true;
			}
			if (!uno && carro.getInfraestructura().getTipo().equals("Esclusa")) {
				uno = true;
			}
			if (!uno
					&& carro.getInfraestructura().getTipo().equals("Compuerta")) {
				uno = true;
			}
			if (!uno && carro.getInfraestructura().getTipo().equals("Deposito")) {
				uno = true;
			}
			if (!uno && carro.getInfraestructura().getTipo().equals("Punto")) {
				if (carro.getSentido().equals(EnumSentido.HACIA_DEPOSITO)) {
					if (carro.getInfraestructura().getId().intValue() != 4) {
						uno = true;
					}
				} else {
					if ((carro.getInfraestructura().getId().intValue() != 4)
							&& (carro.getInfraestructura().getId().intValue() != 2)) {
						uno = true;
					}
				}
			}
			boolean dos = false;
			carro = listCarro.get(1);
			if (carro.getSentido().equals(EnumSentido.HACIA_DEPOSITO)) {
				if (carro.getInfraestructura().getTipo().equals("Camino")) {
					if (carro.getInfraestructura().getId().intValue() == 6) {
						if (carro.getPosicion().getY() <= Configuracion.LARGO_CAMINO_DESCANSO) {
							dos = true;
						}
					} else {
						dos = true;
					}
				}
			} else {
				if (carro.getInfraestructura().getTipo().equals("Camino")) {
					if (carro.getInfraestructura().getId().intValue() != 6) {
						uno = true;
					}
				}
			}
			if (!dos && carro.getInfraestructura().getTipo().equals("Descanso")) {
				dos = true;
			}
			if (!dos && carro.getInfraestructura().getTipo().equals("Esclusa")) {
				dos = true;
			}
			if (!dos
					&& carro.getInfraestructura().getTipo().equals("Compuerta")) {
				dos = true;
			}
			if (!dos && carro.getInfraestructura().getTipo().equals("Deposito")) {
				dos = true;
			}
			if (!dos && carro.getInfraestructura().getTipo().equals("Punto")) {
				if (carro.getSentido().equals(EnumSentido.HACIA_DEPOSITO)) {
					if (carro.getInfraestructura().getId().intValue() != 4) {
						dos = true;
					}
				} else {
					if ((carro.getInfraestructura().getId().intValue() != 4)
							&& (carro.getInfraestructura().getId().intValue() != 2)) {
						dos = true;
					}
				}
			}
			boolean tres = false;
			carro = listCarro.get(2);
			if (carro.getSentido().equals(EnumSentido.HACIA_DEPOSITO)) {
				if (carro.getInfraestructura().getTipo().equals("Camino")) {
					if (carro.getInfraestructura().getId().intValue() == 6) {
						if (carro.getPosicion().getY() <= Configuracion.LARGO_CAMINO_DESCANSO) {
							tres = true;
						}
					} else {
						tres = true;
					}
				}
			} else {
				if (carro.getInfraestructura().getTipo().equals("Camino")) {
					if (carro.getInfraestructura().getId().intValue() != 6) {
						uno = true;
					}
				}
			}
			if (!tres
					&& carro.getInfraestructura().getTipo().equals("Descanso")) {
				tres = true;
			}
			if (!tres && carro.getInfraestructura().getTipo().equals("Esclusa")) {
				tres = true;
			}
			if (!tres
					&& carro.getInfraestructura().getTipo().equals("Compuerta")) {
				tres = true;
			}
			if (!tres
					&& carro.getInfraestructura().getTipo().equals("Deposito")) {
				tres = true;
			}
			if (!tres && carro.getInfraestructura().getTipo().equals("Punto")) {
				if (carro.getSentido().equals(EnumSentido.HACIA_DEPOSITO)) {
					if (carro.getInfraestructura().getId().intValue() != 4) {
						tres = true;
					}
				} else {
					if ((carro.getInfraestructura().getId().intValue() != 4)
							&& (carro.getInfraestructura().getId().intValue() != 2)) {
						tres = true;
					}
				}
			}
			if (car.getId().intValue() == 1) {
				return ((dos) && (tres));
			} else if (car.getId().intValue() == 2) {
				return ((uno) && (tres));
			} else if (car.getId().intValue() == 3) {
				return ((uno) && (dos));
			}
			return false;
		} catch (Exception e) {
			logger.error(e.getMessage());
			throw e;
		}
	}

	private void avanzarCaminoIrDescanso(Carro carro) throws Exception {
		try {
			Camino camino = (Camino) carro.getInfraestructura();
			switch (carro.getId().intValue()) {
			case (1):
				switch (camino.getId().intValue()) {
				case (1):
					avanzarCamino(carro);
					break;
				case (4):
					if (carro.getPosicion().getX() >= camino.getLargoDescanso()) {
						carro.setInfraestructura(camino.getPuntoDescanso()
								.getAnterior());
					} else {
						avanzarCamino(carro);
						if (carro.getPosicion().getX() >= camino
								.getLargoDescanso()) {
							carro.getPosicion().setX(camino.getLargoDescanso());
						}
					}
					break;
				case (6):
					avanzarCamino(carro);
					break;
				}
				break;
			case (2):
				switch (camino.getId().intValue()) {
				case (2):
					if (carro.getPosicion().getY() >= camino.getLargoDescanso()) {
						carro.setInfraestructura(camino.getPuntoDescanso()
								.getPosterior());
					} else {
						avanzarCamino(carro);
						if (carro.getPosicion().getY() >= camino
								.getLargoDescanso()) {
							carro.getPosicion().setY(camino.getLargoDescanso());
						}
					}
					break;
				case (6): // 6
					avanzarCamino(carro);
					break;
				}
				break;
			case (3):
				switch (camino.getId().intValue()) {
				case (3):
					avanzarCamino(carro);
					break;
				case (5):
					if (carro.getPosicion().getX() >= camino.getLargoDescanso()) {
						carro.setInfraestructura(camino.getPuntoDescanso()
								.getPosterior());
					} else {
						avanzarCamino(carro);
						if (carro.getPosicion().getX() >= camino
								.getLargoDescanso()) {
							carro.getPosicion().setX(camino.getLargoDescanso());
						}
					}
					break;
				case (6):
					avanzarCamino(carro);
					break;
				}
				break;
			}
		} catch (Exception e) {
			logger.error(e.getMessage());
			throw e;
		}
	}

	private void avanzarPuntoIrDescanso(Carro carro) throws Exception {
		try {
			avanzarPunto(carro);
		} catch (Exception e) {
			logger.error(e.getMessage());
			throw e;
		}
	}

	private void retrocederCaminoIrDescanso(Carro carro) throws Exception {
		try {
			Camino camino = (Camino) carro.getInfraestructura();
			switch (carro.getId().intValue()) {
			case (1):
				switch (camino.getId().intValue()) {
				case (1):
					retrocederCamino(carro);
					break;
				case (4):
					retrocederCamino(carro);
					break;
				case (6):
					retrocederCamino(carro);
					break;
				}
				break;
			case (2):
				switch (camino.getId().intValue()) {
				case (2):
					retrocederCamino(carro);
					break;
				case (6):
					retrocederCamino(carro);
					break;
				}
				break;
			case (3):
				switch (camino.getId().intValue()) {
				case (3):
					retrocederCamino(carro);
					break;
				case (5):
					retrocederCamino(carro);
					break;
				case (6):
					retrocederCamino(carro);
					break;
				}
				break;
			}
		} catch (Exception e) {
			logger.error(e.getMessage());
			throw e;
		}
	}

	private void retrocederPuntoIrDescanso(Carro carro) throws Exception {
		try {
			retrocederPunto(carro);
		} catch (Exception e) {
			logger.error(e.getMessage());
			throw e;
		}
	}

	public void irADescanso(Carro carro) throws Exception {
		try {
			if (carro.getSentido().equals(EnumSentido.HACIA_RECIPIENTE)) {
				avanzarGeneral(carro);
				if (carro.getInfraestructura().getTipo().equals("Deposito")) {
					avanzarDeposito(carro);
				} else if (carro.getInfraestructura().getTipo()
						.equals("Esclusa")) {
					avanzarEsclusa(carro);
				} else if (carro.getInfraestructura().getTipo()
						.equals("Compuerta")) {
					avanzarCompuerta(carro);
				} else if (carro.getInfraestructura().getTipo().equals("Punto")) {
					avanzarPuntoIrDescanso(carro);
				} else if (carro.getInfraestructura().getTipo()
						.equals("Descanso")) {
					avanzarDescanso(carro);
				} else if (carro.getInfraestructura().getTipo()
						.equals("Camino")) {
					avanzarCaminoIrDescanso(carro);
				}
			} else {
				if (carro.getInfraestructura().getTipo().equals("Deposito")) {
					retrocederDeposito(carro);
				} else if (carro.getInfraestructura().getTipo()
						.equals("Esclusa")) {
					retrocederEsclusa(carro);
				} else if (carro.getInfraestructura().getTipo()
						.equals("Compuerta")) {
					retrocederCompuerta(carro);
				} else if (carro.getInfraestructura().getTipo().equals("Punto")) {
					retrocederPuntoIrDescanso(carro);
				} else if (carro.getInfraestructura().getTipo()
						.equals("Descanso")) {
					retrocederDescanso(carro);
				} else if (carro.getInfraestructura().getTipo()
						.equals("Camino")) {
					retrocederCaminoIrDescanso(carro);
				}
			}
		} catch (Exception e) {
			logger.error(e.getMessage());
			throw e;
		}
	}

	public int cantidadCarrosYendoPorRecipientes() throws Exception {
		try {
			int retorno = 0;
			for (Carro carro : listCarro) {
				if (carro.getOrden().equals(EnumOrden.IR_BUSCAR_RECIPIENTE)) {
					retorno++;
				}
			}
			return retorno;
		} catch (Exception e) {
			logger.error(e.getMessage());
			throw e;
		}
	}

	private void retrocederGeneral(Carro carro) throws Exception {
		try {
			if (carro.getInfraestructura().getPosterior() != null
					&& carro.getInfraestructura().getPosterior().getTipo()
							.equals("Esclusa")) {
				((Esclusa) carro.getInfraestructura().getPosterior())
						.setAbierta(false);
			}
		} catch (Exception e) {
			logger.error(e.getMessage());
			throw e;
		}
	}

	private void retrocederDeposito(Carro carro) throws Exception {
		try {
			if ((seguir())
					&& (carro.getInfraestructura().getTipo().equals("Deposito"))) {
				carro.setPosicion(new Posicion(0, 0));
				deposito.getListPosterior().get(carro.getId().intValue() - 1)
						.setAbierta(false);
				((Esclusa) deposito.getListPosterior()
						.get(carro.getId().intValue() - 1).getPosterior()
						.getPosterior()).setAbierta(false);
				if (carro.getRecipiente() != null) {
					getServicioDepositoAlmacenamiento().dejarRecipiente(carro);
				}
				if (getServicioSistemaGrua().getCantidadRecipientes() > cantidadCarrosYendoPorRecipientes()) {
					carro.setSentido(EnumSentido.HACIA_RECIPIENTE);
				}
				if (cantidadCarrosYendoPorRecipientes() == 0 && getServicioSistemaGrua().hayRecipientesPorEntregar()) {
					listCarro.get(0).setOrden(EnumOrden.IR_BUSCAR_RECIPIENTE);
				}
				/*
				 * else if ((!servicioSistemaGrua.hayRecipientesPorEntregar())
				 * && (cantidadCarrosYendoPorRecipientes() == 0)) { parar(); }
				 */
				logger.debug("Cantidad de recipientes: "
						+ getServicioSistemaGrua().getCantidadRecipientes());

				continuar = false;
			}
		} catch (Exception e) {
			logger.error(e.getMessage());
			throw e;
		}
	}

	private void retrocederEsclusa(Carro carro) throws Exception {
		try {
			if ((seguir())
					&& (carro.getInfraestructura().getTipo().equals("Esclusa"))) {
				Esclusa esclusa = (Esclusa) carro.getInfraestructura();
				carro.setPosicion(new Posicion(0, 0));
				if ((continuar && ciclador.isContinuar())
						&& (!esclusa.isAbierta())
						&& noHayEsclusasAbiertas()
						&& (getCarroEnMedioDeCompuerta() == -1 || getCarroEnMedioDeCompuerta() == carro
								.getId())) {
					esclusa.setAbierta(true);
					continuar = false;
				}
				if ((seguir()) && (esclusa.isAbierta())) {
					carro.setInfraestructura(esclusa.getAnterior());
					activarSensoresProximidad(carro, carro.getInfraestructura());
					continuar = false;
				}
			}
		} catch (Exception e) {
			logger.error(e.getMessage());
			throw e;
		}
	}

	private void retrocederCompuerta(Carro carro) throws Exception {
		try {
			if ((seguir())
					&& (carro.getInfraestructura().getTipo()
							.equals("Compuerta"))) {
				Compuerta compuerta = (Compuerta) carro.getInfraestructura();
				compuerta.getPosterior().setAbierta(false);
				Esclusa esclusa = compuerta.getAnterior();
				carro.setInfraestructura(esclusa);
				activarSensoresProximidad(carro, esclusa);
				carro.setPosicion(new Posicion(0, 0));
				continuar = false;
			}
		} catch (Exception e) {
			logger.error(e.getMessage());
			throw e;
		}
	}

	private void retrocederCamino(Carro carro) throws Exception {
		try {
			if ((seguir())
					&& (carro.getInfraestructura().getTipo().equals("Camino"))) {
				Camino camino = (Camino) carro.getInfraestructura();
				if (carro.getPosicion().getX() <= 0
						&& carro.getPosicion().getY() <= 0) {
					if (camino.getId().intValue() != 6) {
						carro.getPosicion().setX(Configuracion.LARGO_CAMINO);
						carro.getPosicion().setY(Configuracion.LARGO_CAMINO);
					} else {
						carro.getPosicion().setX(0);
						carro.getPosicion()
								.setY(Configuracion.LARGO_CAMINO_EXT);
					}
					carro.setInfraestructura(carro.getInfraestructura()
							.getAnterior());
					if (carro.getInfraestructura().getTipo().equals("Esclusa")) {
						carro.getPosicion().setX(0);
						carro.getPosicion().setY(0);
					}
				} else {
					if (!camino.isHorizontal()) {
						carro.getPosicion().setY(
								carro.getPosicion().getY()
										- carro.getVelocidad());
					} else {
						carro.getPosicion().setX(
								carro.getPosicion().getX()
										- carro.getVelocidad());
					}
				}
				continuar = false;
			}
		} catch (Exception e) {
			logger.error(e.getMessage());
			throw e;
		}
	}

	private void retrocederPunto(Carro carro) throws Exception {
		try {
			if ((seguir())
					&& (carro.getInfraestructura().getTipo().equals("Punto"))) {
				Punto punto = (Punto) carro.getInfraestructura();
				if (punto.getId().intValue() == 2) {
					carro.setInfraestructura(punto.getListCaminoAnterior().get(
							carro.getId().intValue() - 1));
				} else {
					carro.setInfraestructura(carro.getInfraestructura()
							.getAnterior());
				}
				Camino camino = (Camino) carro.getInfraestructura();
				if (camino.isHorizontal()) {
					if (carro.getVelocidad() == 1) {
						carro.setPosicion(new Posicion(
								Configuracion.LARGO_CAMINO - 1, 0));
					} else if (carro.getVelocidad() == 2) {
						carro.setPosicion(new Posicion(
								Configuracion.LARGO_CAMINO - 2, 0));
					} else if (carro.getVelocidad() == 3) {
						carro.setPosicion(new Posicion(
								Configuracion.LARGO_CAMINO - 1, 0));
					} else if (carro.getVelocidad() == 0) {
						carro.setPosicion(new Posicion(
								Configuracion.LARGO_CAMINO, 0));
					}
				} else if (camino.getId().intValue() == 6) {
					if (carro.getVelocidad() == 1) {
						carro.setPosicion(new Posicion(0,
								Configuracion.LARGO_CAMINO_EXT - 1));
					} else if (carro.getVelocidad() == 2) {
						carro.setPosicion(new Posicion(0,
								Configuracion.LARGO_CAMINO_EXT - 2));
					} else if (carro.getVelocidad() == 3) {
						carro.setPosicion(new Posicion(0,
								Configuracion.LARGO_CAMINO_EXT - 3));
					} else if (carro.getVelocidad() == 0) {
						carro.setPosicion(new Posicion(0,
								Configuracion.LARGO_CAMINO_EXT));
					}
				} else {
					if (carro.getVelocidad() == 1) {
						carro.setPosicion(new Posicion(0,
								Configuracion.LARGO_CAMINO - 1));
					} else if (carro.getVelocidad() == 2) {
						carro.setPosicion(new Posicion(0,
								Configuracion.LARGO_CAMINO - 2));
					} else if (carro.getVelocidad() == 3) {
						carro.setPosicion(new Posicion(0,
								Configuracion.LARGO_CAMINO - 1));
					} else if (carro.getVelocidad() == 0) {
						carro.setPosicion(new Posicion(0,
								Configuracion.LARGO_CAMINO));
					}
				}
				continuar = false;
			}
		} catch (Exception e) {
			logger.error(e.getMessage());
			throw e;
		}
	}

	private void retrocederDescanso(Carro carro) throws Exception {
		try {
			if ((seguir())
					&& (carro.getInfraestructura().getTipo().equals("Descanso"))) {
				Descanso descanso = (Descanso) carro.getInfraestructura();
				switch (carro.getId().intValue()) {
				case (1):
					if (descanso.isHorizontal()) {
						carro.getPosicion().setX(
								carro.getPosicion().getX()
										- carro.getVelocidad());
						if (carro.getPosicion().getX() <= 0) {
							carro.setInfraestructura(descanso.getPosterior());
						}
					} else {
						carro.getPosicion().setY(
								carro.getPosicion().getY()
										- carro.getVelocidad());
						if (carro.getPosicion().getY() <= Configuracion.LARGO_CAMINO_DESCANSO) {
							carro.setInfraestructura(descanso.getPosterior());
						}
					}
					break;
				case (2):
					if (descanso.isHorizontal()) {
						carro.getPosicion().setX(
								carro.getPosicion().getX()
										- carro.getVelocidad());
						if (carro.getPosicion().getX() <= Configuracion.LARGO_CAMINO_DESCANSO) {
							carro.setInfraestructura(descanso.getAnterior());
						}
					} else {
						carro.getPosicion().setY(
								carro.getPosicion().getY()
										- carro.getVelocidad());
						if (carro.getPosicion().getY() <= Configuracion.LARGO_CAMINO_DESCANSO) {
							carro.setInfraestructura(descanso.getAnterior());
						}
					}
					break;
				case (3):
					if (descanso.isHorizontal()) {
						carro.getPosicion().setX(
								carro.getPosicion().getX()
										- carro.getVelocidad());
						if (carro.getPosicion().getX() <= Configuracion.LARGO_CAMINO_DESCANSO) {
							carro.setInfraestructura(descanso.getAnterior());
						}
					} else {
						carro.getPosicion().setY(
								carro.getPosicion().getY()
										- carro.getVelocidad());
						if (carro.getPosicion().getY() <= Configuracion.LARGO_CAMINO_DESCANSO) {
							carro.setInfraestructura(descanso.getAnterior());
						}
					}
					break;
				}
			}
		} catch (Exception e) {
			logger.error(e.getMessage());
			throw e;
		}
	}

	private void buscarDeposito(Carro carro) throws Exception {
		try {
			retrocederGeneral(carro);
			retrocederDeposito(carro);
			retrocederEsclusa(carro);
			retrocederCompuerta(carro);
			retrocederPunto(carro);
			retrocederDescanso(carro);
			retrocederCamino(carro);
		} catch (Exception e) {
			logger.error(e.getMessage());
			throw e;
		}
	}

	private void avanzarGeneral(Carro carro) throws Exception {
		try {
			if (carro.getInfraestructura().getAnterior() != null
					&& carro.getInfraestructura().getAnterior().getTipo()
							.equals("Esclusa")) {
				((Esclusa) carro.getInfraestructura().getAnterior())
						.setAbierta(false);
			}
		} catch (Exception e) {
			logger.error(e.getMessage());
			throw e;
		}
	}

	private void avanzarDeposito(Carro carro) throws Exception {
		try {
			if ((seguir())
					&& (carro.getInfraestructura().getTipo().equals("Deposito"))) {
				// if (servicioSistemaGrua.hayRecipientesPorEntregar()) {
				Esclusa esclusa = deposito.getListPosterior().get(
						carro.getId().intValue() - 1);
				carro.setInfraestructura(esclusa);
				activarSensoresProximidad(carro, esclusa);
				// }
				continuar = false;
			}
		} catch (Exception e) {
			logger.error(e.getMessage());
			throw e;
		}
	}

	private void avanzarEsclusa(Carro carro) throws Exception {
		try {
			if ((seguir())
					&& (carro.getInfraestructura().getTipo().equals("Esclusa"))) {
				Esclusa esclusa = (Esclusa) carro.getInfraestructura();
				if ((continuar && ciclador.isContinuar())
						&& (!esclusa.isAbierta())
						&& noHayEsclusasAbiertas()
						&& (getCarroEnMedioDeCompuerta() == -1 || getCarroEnMedioDeCompuerta() == carro
								.getId())) {
					esclusa.setAbierta(true);
					continuar = false;
				}
				if ((seguir()) && (esclusa.isAbierta())) {
					carro.setInfraestructura(esclusa.getPosterior());
					activarSensoresProximidad(carro, carro.getInfraestructura());
					continuar = false;
				}
			}
		} catch (Exception e) {
			logger.error(e.getMessage());
			throw e;
		}
	}

	private void avanzarCompuerta(Carro carro) throws Exception {
		try {
			if ((seguir())
					&& (carro.getInfraestructura().getTipo()
							.equals("Compuerta"))) {
				Compuerta compuerta = (Compuerta) carro.getInfraestructura();
				compuerta.getAnterior().setAbierta(false);
				Esclusa esclusa = compuerta.getPosterior();
				carro.setInfraestructura(esclusa);
				activarSensoresProximidad(carro, esclusa);
				continuar = false;
			}
		} catch (Exception e) {
			logger.error(e.getMessage());
			throw e;
		}
	}

	private void avanzarCamino(Carro carro) throws Exception {
		try {
			if ((seguir())
					&& (carro.getInfraestructura().getTipo().equals("Camino"))) {
				Camino camino = (Camino) carro.getInfraestructura();
				if (carro.getPosicion().getX() >= camino.getLargo().longValue() - 1
						|| carro.getPosicion().getY() >= camino.getLargo()
								.longValue() - 1) {
					if (camino.getId().intValue() == 6) {
						if (carro.getRecipiente() == null) {
							getServicioSistemaGrua().entregarRecipiente(carro);
							carro.setSentido(EnumSentido.HACIA_DEPOSITO);
						}
					}
					if (camino.getId().intValue() != 6) {
						carro.getPosicion().setX(0);
						carro.getPosicion().setY(0);
					}
					carro.setInfraestructura(carro.getInfraestructura()
							.getPosterior());
				} else {
					if (!camino.isHorizontal()) {
						carro.getPosicion().setY(
								carro.getPosicion().getY()
										+ carro.getVelocidad());
					} else {
						carro.getPosicion().setX(
								carro.getPosicion().getX()
										+ carro.getVelocidad());
					}
				}
				continuar = false;
			}
		} catch (Exception e) {
			logger.error(e.getMessage());
			throw e;
		}
	}

	private void avanzarPunto(Carro carro) throws Exception {
		try {
			if ((seguir())
					&& (carro.getInfraestructura().getTipo().equals("Punto"))) {
				Punto punto = (Punto) carro.getInfraestructura();
				if (carro.getOrden().equals(EnumOrden.IR_DESCANSO)) {
					if (punto.getPosterior().getTipo().equals("Descanso")) {
						if (punto.getPropietario() != null
								&& punto.getId().intValue() == 11) {
							if (sePuedeSalirDelDescanso(carro)) {
								carro.setCantidadVueltasDescanso(0);
								carro.setInfraestructura(punto.getPropietario());
								continuar = false;
								carro.getPosicion().setX(0);
								carro.getPosicion().setY(
										Configuracion.LARGO_CAMINO_DESCANSO);
								carro.setOrden(EnumOrden.IR_BUSCAR_RECIPIENTE);
							}
						} else {
							if (punto.getId().intValue() == 12) {
								carro.setInfraestructura(punto.getAnterior());
							} else {
								carro.setInfraestructura(punto.getPosterior());
							}
						}
					} else {
						if (punto.getId().intValue() == 4) {
							if (carro.getRecipiente() == null) {
								getServicioSistemaGrua().entregarRecipiente(
										carro);
								carro.setSentido(EnumSentido.HACIA_DEPOSITO);
							}
						}
						carro.setInfraestructura(punto.getPosterior());
						continuar = false;
					}
				} else {
					if (punto.getId().intValue() == 4) {
						if (carro.getRecipiente() == null) {
							getServicioSistemaGrua().entregarRecipiente(carro);
							carro.setSentido(EnumSentido.HACIA_DEPOSITO);
						}
					}
					carro.setInfraestructura(punto.getPosterior());
					continuar = false;
				}
			}
		} catch (Exception e) {
			logger.error(e.getMessage());
			throw e;
		}
	}

	private boolean isOtroCarroSobreFinDeDescanso(Carro carro) {
		for (Carro car : listCarro) {
			if (car.getId().intValue() != carro.getId().intValue()) {
				if (car.getInfraestructura().getTipo().equals("Descanso")) {
					if (car.getInfraestructura().getId().intValue() == 6) {
						if (car.getPosicion().getX() >= 2) {
							if (carro.getInfraestructura().getTipo()
									.equals("Descanso")) {
								if (carro.getInfraestructura().getId()
										.intValue() == 6) {
									return true;
								}
							}
						}
					}
				}
			}
		}
		return false;
	}

	private void avanzarDescanso(Carro carro) throws Exception {
		try {
			if ((seguir())
					&& (carro.getInfraestructura().getTipo().equals("Descanso"))) {
				carro.setCantidadVueltasDescanso(carro
						.getCantidadVueltasDescanso() + 1);
				Descanso descanso = (Descanso) carro.getInfraestructura();
				switch (carro.getId().intValue()) {
				case (1):
					if (descanso.isHorizontal()) {
						if (carro.getPosicion().getX() >= Configuracion.LARGO_CAMINO_DESCANSO) {
							if (descanso.getId().intValue() == 7) {
								if (sePuedeSalirDelDescanso(carro)) {
									carro.setParado(false);
									carro.setCantidadVueltasDescanso(0);
									carro.setInfraestructura(descanso
											.getAnterior());
									carro.getPosicion().setX(0);
									carro.getPosicion().setY(0);
								} else {
									carro.setParado(true);
								}
							} else {
								carro.setInfraestructura(descanso.getAnterior());
								carro.getPosicion().setX(0);
								carro.getPosicion().setY(0);
							}
						} else {
							if (isOtroCarroSobreFinDeDescanso(carro)) {
								if (carro.getPosicion().getX() <= 1) {
									carro.setParado(false);
									carro.getPosicion().setX(
											carro.getPosicion().getX()
													+ carro.getVelocidad());
								} else {
									carro.setParado(true);
								}
							} else {
								carro.setParado(false);
								carro.getPosicion().setX(
										carro.getPosicion().getX()
												+ carro.getVelocidad());
							}
						}
					} else {
						carro.getPosicion().setY(
								carro.getPosicion().getY()
										+ carro.getVelocidad());
						if (carro.getPosicion().getY() >= Configuracion.LARGO_CAMINO_DESCANSO) {
							carro.setInfraestructura(descanso.getAnterior());
							carro.getPosicion().setX(0);
							carro.getPosicion().setY(0);
						}
					}
					break;
				case (2):
					if (descanso.isHorizontal()) {
						if (carro.getPosicion().getX() >= Configuracion.LARGO_CAMINO_DESCANSO) {
							if (descanso.getId().intValue() == 6) {
								if (sePuedeSalirDelDescanso(carro)) {
									carro.setParado(false);
									carro.setCantidadVueltasDescanso(0);
									carro.setInfraestructura(descanso
											.getPosterior());
									carro.getPosicion().setX(0);
									carro.getPosicion().setY(0);
								} else {
									carro.setParado(true);
								}
							} else {
								carro.setInfraestructura(descanso
										.getPosterior());
								carro.getPosicion().setX(0);
								carro.getPosicion().setY(0);
							}
						} else {
							if (isOtroCarroSobreFinDeDescanso(carro)) {
								if (carro.getPosicion().getX() <= 1) {
									carro.setParado(false);
									carro.getPosicion().setX(
											carro.getPosicion().getX()
													+ carro.getVelocidad());
								} else {
									carro.setParado(true);
								}
							} else {
								carro.setParado(false);
								carro.getPosicion().setX(
										carro.getPosicion().getX()
												+ carro.getVelocidad());
							}
						}
					} else {
						carro.getPosicion().setY(
								carro.getPosicion().getY()
										+ carro.getVelocidad());
						if (carro.getPosicion().getY() >= Configuracion.LARGO_CAMINO_DESCANSO) {
							carro.setInfraestructura(descanso.getPosterior());
							carro.getPosicion().setX(0);
							carro.getPosicion().setY(0);
						}
					}
					break;
				case (3):
					if (descanso.isHorizontal()) {
						if (carro.getPosicion().getX() >= Configuracion.LARGO_CAMINO_DESCANSO) {
							if (descanso.getId().intValue() == 6) {
								if (sePuedeSalirDelDescanso(carro)) {
									carro.setParado(false);
									carro.setCantidadVueltasDescanso(0);
									carro.setInfraestructura(descanso
											.getPosterior());
									carro.getPosicion().setX(0);
									carro.getPosicion().setY(0);
								} else {
									carro.setParado(true);
								}
							} else {
								carro.setInfraestructura(descanso
										.getPosterior());
								carro.getPosicion().setX(0);
								carro.getPosicion().setY(0);
							}
						} else {
							if (isOtroCarroSobreFinDeDescanso(carro)) {
								if (carro.getPosicion().getX() <= 1) {
									carro.setParado(false);
									carro.getPosicion().setX(
											carro.getPosicion().getX()
													+ carro.getVelocidad());
								} else {
									carro.setParado(true);
								}
							} else {
								carro.setParado(false);
								carro.getPosicion().setX(
										carro.getPosicion().getX()
												+ carro.getVelocidad());
							}
						}
					} else {
						carro.getPosicion().setY(
								carro.getPosicion().getY()
										+ carro.getVelocidad());
						if (carro.getPosicion().getY() >= Configuracion.LARGO_CAMINO_DESCANSO) {
							carro.setInfraestructura(descanso.getPosterior());
							carro.getPosicion().setX(0);
							carro.getPosicion().setY(0);
						}
					}
					break;
				}
			}
		} catch (Exception e) {
			logger.error(e.getMessage());
			throw e;
		}
	}

	private void buscarRecipiente(Carro carro) throws Exception {
		try {
			avanzarGeneral(carro);
			avanzarDeposito(carro);
			avanzarEsclusa(carro);
			avanzarCompuerta(carro);
			avanzarPunto(carro);
			avanzarDescanso(carro);
			avanzarCamino(carro);
		} catch (Exception e) {
			logger.error(e.getMessage());
			throw e;
		}
	}

	private Long getCarroEnMedioDeCompuerta() throws Exception {
		try {
			for (Carro c : listCarro) {
				logger.debug(c.toString());
				if ((c.getInfraestructura() != null)
						&& (c.getInfraestructura().getAnterior() != null)
						&& (c.getInfraestructura().getAnterior().getTipo()
								.equals("Compuerta"))) {
					return c.getId();
				}
			}
			return -1L;
		} catch (Exception e) {
			logger.error(e.getMessage());
			throw e;
		}
	}

	private boolean noHayEsclusasAbiertas() throws Exception {
		try {
			for (Esclusa esc : listEsclusa) {
				if (esc.isAbierta()) {
					return false;
				}
			}
			return true;
		} catch (Exception e) {
			logger.error(e.getMessage());
			throw e;
		}
	}

	public void ciclar(Observer o, int escenario) throws Exception {
		try {
			this.observer = o;
			ciclador = new Ciclador(this);
			this.setEscenario(escenario);
			ciclador.start();
		} catch (Exception e) {
			logger.error(e.getMessage());
			throw e;
		}
	}

	public void parar() throws Exception {
		try {
			ciclador.parar();
		} catch (Exception e) {
			logger.error(e.getMessage());
			throw e;
		}
	}

	public void setListCarro(List<Carro> listCarro) {
		this.listCarro = listCarro;
	}

	public List<Carro> getListCarro() {
		return listCarro;
	}

	public void setListEsclusa(List<Esclusa> listEsclusa) {
		this.listEsclusa = listEsclusa;
	}

	public List<Esclusa> getListEsclusa() {
		return listEsclusa;
	}

	public void setListSensor(List<Sensor> listSensor) {
		this.listSensor = listSensor;
	}

	public List<Sensor> getListSensor() {
		return listSensor;
	}

	private Object[] getTiempoHastaUnificado(Carro carro) throws Exception {
		try {
			boolean seteado = false;
			int tiempoCarro = 0;
			switch (carro.getId().intValue()) {
			case (1):
				seteado = false;
				Carro carro1 = carro;
				int tiempoCarro1 = 0;
				if (carro1.getVelocidad() == 0) {
					tiempoCarro1 = 100;
					seteado = true;
				} else {
					if (carro1.getInfraestructura().getTipo().equals("Camino")) {
						if (carro1.getInfraestructura().getId().intValue() == 1) {
							tiempoCarro1 = ((int) Configuracion.LARGO_CAMINO)
									/ carro1.getVelocidad()
									+ (((int) Configuracion.LARGO_CAMINO) - ((int) carro1
											.getPosicion().getY()))
									/ carro1.getVelocidad();
							seteado = true;
						} else if (carro1.getInfraestructura().getId()
								.intValue() == 4) {
							tiempoCarro1 = (((int) Configuracion.LARGO_CAMINO) - ((int) carro1
									.getPosicion().getX()))
									/ carro1.getVelocidad();
							seteado = true;
						}
					} else if (carro1.getInfraestructura().getTipo()
							.equals("Punto")) {
						if (carro1.getInfraestructura().getId().intValue() == 1) {
							tiempoCarro1 = ((int) Configuracion.LARGO_CAMINO)
									/ carro1.getVelocidad();
							seteado = true;
						} else if (carro1.getInfraestructura().getId()
								.intValue() == 2) {
							tiempoCarro1 = 0;
							seteado = true;
						} else if (carro1.getInfraestructura().getId()
								.intValue() == 4) {
							tiempoCarro1 = 0;
							seteado = true;
						} else if (carro1.getInfraestructura().getId()
								.intValue() == 10) {
							tiempoCarro1 = ((int) Configuracion.LARGO_CAMINO_DESCANSO);
							seteado = true;
						} else if (carro1.getInfraestructura().getId()
								.intValue() == 11) {
							tiempoCarro1 = 0;
							seteado = true;
						} else if (carro1.getInfraestructura().getId()
								.intValue() == 12) {
							tiempoCarro1 = ((int) Configuracion.LARGO_CAMINO_DESCANSO);
							seteado = true;
						}
					} else if (carro1.getInfraestructura().getTipo()
							.equals("Descanso")) {
						if (carro1.getInfraestructura().getId().intValue() == 7) {
							tiempoCarro1 = (((int) Configuracion.LARGO_CAMINO_DESCANSO) - (int) carro1
									.getPosicion().getX())
									/ carro1.getVelocidad();
							seteado = true;
						} else if (carro1.getInfraestructura().getId()
								.intValue() == 8) {
							tiempoCarro1 = ((int) Configuracion.LARGO_CAMINO_DESCANSO)
									+ (((int) Configuracion.LARGO_CAMINO_DESCANSO) - (int) carro1
											.getPosicion().getY())
									/ carro1.getVelocidad();
							seteado = true;
						}
					} else {
						tiempoCarro1 = ((int) (2 * Configuracion.LARGO_CAMINO))
								/ carro1.getVelocidad();
						seteado = true;
					}
					if (!seteado) {
						tiempoCarro1 = ((int) (2 * Configuracion.LARGO_CAMINO))
								/ carro1.getVelocidad();
					}
					tiempoCarro = tiempoCarro1;
				}
				break;
			case (2):
				seteado = false;
				Carro carro2 = carro;
				int tiempoCarro2 = 0;
				if (carro2.getVelocidad() == 0) {
					tiempoCarro2 = 100;
					seteado = true;
				} else {
					if (carro2.getInfraestructura().getTipo().equals("Camino")) {
						if (carro2.getInfraestructura().getId().intValue() == 2) {
							tiempoCarro2 = (((int) Configuracion.LARGO_CAMINO) - ((int) carro2
									.getPosicion().getY()))
									/ carro2.getVelocidad();
							seteado = true;
						}
					} else if (carro2.getInfraestructura().getTipo()
							.equals("Punto")) {
						if (carro2.getInfraestructura().getId().intValue() == 2) {
							tiempoCarro2 = 0;
							seteado = true;
						} else if (carro2.getInfraestructura().getId()
								.intValue() == 4) {
							tiempoCarro2 = 0;
							seteado = true;
						}
					} else if (carro2.getInfraestructura().getTipo()
							.equals("Descanso")) {
						if (carro2.getInfraestructura().getId().intValue() == 6) {
							tiempoCarro2 = (((int) Configuracion.LARGO_CAMINO_DESCANSO) - (int) carro2
									.getPosicion().getX())
									/ carro2.getVelocidad();
							seteado = true;
						} else if (carro2.getInfraestructura().getId()
								.intValue() == 5) {
							tiempoCarro2 = ((int) Configuracion.LARGO_CAMINO_DESCANSO)
									+ (((int) Configuracion.LARGO_CAMINO_DESCANSO) - (int) carro2
											.getPosicion().getY())
									/ carro2.getVelocidad();
							seteado = true;
						} else if (carro2.getInfraestructura().getId()
								.intValue() == 4) {
							tiempoCarro2 = ((int) Configuracion.LARGO_CAMINO)
									+ (((int) Configuracion.LARGO_CAMINO_DESCANSO) - (int) carro2
											.getPosicion().getY())
									/ carro2.getVelocidad();
							seteado = true;
						} else if (carro2.getInfraestructura().getId()
								.intValue() == 3) {
							tiempoCarro2 = 3
									* ((int) Configuracion.LARGO_CAMINO_DESCANSO)
									+ (((int) Configuracion.LARGO_CAMINO_DESCANSO) - (int) carro2
											.getPosicion().getX())
									/ carro2.getVelocidad();
							seteado = true;
						}
					} else {
						tiempoCarro2 = ((int) Configuracion.LARGO_CAMINO)
								/ carro2.getVelocidad();
						seteado = true;
					}
					if (!seteado) {
						tiempoCarro2 = ((int) Configuracion.LARGO_CAMINO)
								/ carro2.getVelocidad();
					}
				}
				tiempoCarro = tiempoCarro2;
				break;
			case (3):
				seteado = false;
				Carro carro3 = carro;
				int tiempoCarro3 = 0;
				if (carro3.getVelocidad() == 0) {
					tiempoCarro3 = 100;
					seteado = true;
				} else {
					if (carro3.getInfraestructura().getTipo().equals("Camino")) {
						if (carro3.getInfraestructura().getId().intValue() == 3) {
							tiempoCarro3 = ((int) Configuracion.LARGO_CAMINO)
									/ carro3.getVelocidad()
									+ (((int) Configuracion.LARGO_CAMINO) - ((int) carro3
											.getPosicion().getY()))
									/ carro3.getVelocidad();
							seteado = true;
						} else if (carro3.getInfraestructura().getId()
								.intValue() == 5) {
							tiempoCarro3 = (((int) Configuracion.LARGO_CAMINO) - ((int) carro3
									.getPosicion().getX()))
									/ carro3.getVelocidad();
							seteado = true;
						}
					} else if (carro3.getInfraestructura().getTipo()
							.equals("Punto")) {
						if (carro3.getInfraestructura().getId().intValue() == 3) {
							tiempoCarro3 = ((int) Configuracion.LARGO_CAMINO)
									/ carro3.getVelocidad();
							seteado = true;
						} else if (carro3.getInfraestructura().getId()
								.intValue() == 2) {
							tiempoCarro3 = 0;
							seteado = true;
						} else if (carro3.getInfraestructura().getId()
								.intValue() == 4) {
							tiempoCarro3 = 0;
							seteado = true;
						}
					} else if (carro3.getInfraestructura().getTipo()
							.equals("Descanso")) {
						if (carro3.getInfraestructura().getId().intValue() == 6) {
							tiempoCarro3 = (((int) Configuracion.LARGO_CAMINO_DESCANSO) - (int) carro3
									.getPosicion().getX())
									/ carro3.getVelocidad();
							seteado = true;
						} else if (carro3.getInfraestructura().getId()
								.intValue() == 5) {
							tiempoCarro3 = ((int) Configuracion.LARGO_CAMINO_DESCANSO)
									+ (((int) Configuracion.LARGO_CAMINO_DESCANSO) - (int) carro3
											.getPosicion().getY())
									/ carro3.getVelocidad();
							seteado = true;
						}
					} else {
						tiempoCarro3 = 2 * ((int) Configuracion.LARGO_CAMINO)
								/ carro3.getVelocidad();
						seteado = true;
					}
					if (!seteado) {
						tiempoCarro3 = 2 * ((int) Configuracion.LARGO_CAMINO)
								/ carro3.getVelocidad();
					}
					tiempoCarro = tiempoCarro3;
				}
				break;
			}
			Object[] retorno = new Object[2];
			retorno[0] = new Integer(tiempoCarro);
			retorno[1] = new Boolean(seteado);
			return retorno;
		} catch (Exception e) {
			logger.error(e.getMessage());
			throw e;
		}
	}

	public Carro getCarroPrimeroEnUnificado() throws Exception {
		try {
			Carro carro = null;
			boolean encontrado = false;
			for (int i = 0; ((i < listCarro.size()) && (!encontrado)); i++) {
				carro = listCarro.get(i);
				if (carro.getInfraestructura().getTipo().equals("Camino")) {
					if (carro.getInfraestructura().getId().intValue() == 6) {
						encontrado = true;
					}
				}
			}
			if (encontrado) {
				return carro;
			}
			carro = null;
			boolean seteado = false;
			Carro carro1 = listCarro.get(0);
			Object[] resultado = getTiempoHastaUnificado(carro1);
			int tiempoCarro1 = (Integer) resultado[0];
			seteado = (Boolean) resultado[1];

			seteado = false;
			Carro carro2 = listCarro.get(1);
			resultado = getTiempoHastaUnificado(carro2);
			int tiempoCarro2 = (Integer) resultado[0];
			seteado = (Boolean) resultado[1];

			seteado = false;
			Carro carro3 = listCarro.get(2);
			resultado = getTiempoHastaUnificado(carro3);
			int tiempoCarro3 = (Integer) resultado[0];
			seteado = (Boolean) resultado[1];
			seteado = false;
			int tiempoMinimo = ((tiempoCarro1 <= tiempoCarro2) && (tiempoCarro1 <= tiempoCarro3)) ? (tiempoCarro1)
					: ((tiempoCarro2 <= tiempoCarro3) ? (tiempoCarro2)
							: (tiempoCarro3));
			if (tiempoMinimo == tiempoCarro1) {
				carro = carro1;
			}
			if (tiempoMinimo == tiempoCarro2) {
				carro = carro2;
			}
			if (tiempoMinimo == tiempoCarro3) {
				carro = carro3;
			}
			if (tiempoMinimo == tiempoCarro1
					&& carro.getCantidadVueltasDescanso() >= carro1
							.getCantidadVueltasDescanso()) {
				carro = carro1;
			}
			if (tiempoMinimo == tiempoCarro2
					&& carro.getCantidadVueltasDescanso() >= carro2
							.getCantidadVueltasDescanso()) {
				carro = carro2;
			}
			if (tiempoMinimo == tiempoCarro3
					&& carro.getCantidadVueltasDescanso() >= carro3
							.getCantidadVueltasDescanso()) {
				carro = carro3;
			}
			return carro;
		} catch (Exception e) {
			logger.error(e.getMessage());
			throw e;
		}
	}

	public void setServicioSistemaGrua(ServicioSistemaGrua servicioSistemaGrua) {
		this.servicioSistemaGrua = servicioSistemaGrua;
	}

	public ServicioSistemaGrua getServicioSistemaGrua() {
		return servicioSistemaGrua;
	}

	public void setServicioDepositoAlmacenamiento(
			ServicioDepositoAlmacenamiento servicioDepositoAlmacenamiento) {
		this.servicioDepositoAlmacenamiento = servicioDepositoAlmacenamiento;
	}

	public ServicioDepositoAlmacenamiento getServicioDepositoAlmacenamiento() {
		return servicioDepositoAlmacenamiento;
	}

	public void setListCaminos(List<Camino> listCaminos) {
		this.listCaminos = listCaminos;
	}

	public List<Camino> getListCaminos() {
		return listCaminos;
	}

	public void setEscenario(int escenario) {
		this.escenario = escenario;
		ciclosDesdePulsarBoton1 = 0;
		ciclosDesdePulsarBoton2 = 0;
		ciclosDesdePulsarBoton3 = 0;
		switch (this.escenario) {
		case (Configuracion.ESCENARIO_UNO_NORMAL):
			ciclosDesdePulsarBoton1 = (int) CICLOS;
			break;
		case (Configuracion.ESCENARIO_DOS_OBSTACULO):
			ciclosDesdePulsarBoton2 = (int) CICLOS;
			break;
		case (Configuracion.ESCENARIO_TRES_VIENTO):
			ciclosDesdePulsarBoton3 = (int) CICLOS;
			break;
		}
	}

	public int getEscenario() {
		return escenario;
	}
}